1
2
3
4 package joeq.ClassLib.Common.java.util.zip;
5
6 import java.util.Enumeration;
7 import java.util.Hashtable;
8 import java.io.RandomAccessFile;
9 import jwutil.util.Assert;
10
11 /***
12 * ZipFile
13 *
14 * @author John Whaley <jwhaley@alum.mit.edu>
15 * @version $Id: ZipFile.java 1941 2004-09-30 03:37:06Z joewhaley $
16 */
17 public abstract class ZipFile implements ZipConstants {
18 public static final boolean TRACE = false;
19
20
21 private String name;
22
23
24 private RandomAccessFile raf;
25 private Hashtable entries;
26 private long cenpos;
27 private long pos;
28
29 private static void initIDs() {
30 }
31
32
33
34
35
36
37
38
39
40
41
42 public native void __init__(java.lang.String name)
43 throws java.io.IOException;
44 public ZipFile(java.lang.String name) throws java.io.IOException {
45 this.__init__(name);
46 }
47 public ZipFile(java.io.File file, int mode) throws java.io.IOException {
48 this(file.getPath());
49
50 Assert._assert(mode == java.util.zip.ZipFile.OPEN_READ);
51 }
52 public java.util.zip.ZipEntry getEntry(String name) {
53 if (TRACE)
54 System.out.println(this +": getting entry " + name);
55 Hashtable entries = this.entries;
56 if (entries == null) {
57
58 return null;
59 }
60 return (java.util.zip.ZipEntry) entries.get(name);
61 }
62 public Enumeration entries() {
63 Hashtable entries = this.entries;
64 return entries.elements();
65 }
66 public int size() {
67 Hashtable entries = this.entries;
68 if (entries == null) {
69
70 return 0;
71 }
72 if (TRACE)
73 System.out.println(this +": getting size = " + entries.size());
74 return entries.size();
75 }
76 public void close() throws java.io.IOException {
77 if (TRACE)
78 System.out.println(this +": closing file");
79 RandomAccessFile raf = this.raf;
80 if (raf != null) {
81 raf.close();
82 this.raf = null;
83 }
84 entries = null;
85 }
86 private java.io.InputStream getInputStream(java.lang.String name)
87 throws java.io.IOException {
88 java.lang.Object o = getEntry(name);
89 return getInputStream((ZipEntry) o);
90 }
91 public java.io.InputStream getInputStream(ZipEntry ze)
92 throws java.io.IOException {
93 if (ze == null)
94 return null;
95 java.io.InputStream in = new ZipFileInputStream(this, ze);
96 if (TRACE)
97 System.out.println(
98 this +": getting input stream for " + ze + " = " + in);
99 switch (ze.getMethod()) {
100 case java.util.zip.ZipEntry.STORED :
101 return in;
102 case java.util.zip.ZipEntry.DEFLATED :
103 java.util.zip.Inflater inflater;
104 inflater = this.getInflater();
105 if (TRACE)
106 System.out.println(this +": using inflater " + inflater);
107
108 return new InflaterInputStreamWrapper(this, in, inflater);
109 default :
110 throw new java.util.zip.ZipException(
111 "invalid compression method");
112 }
113 }
114 private native java.util.zip.Inflater getInflater();
115 private native void releaseInflater(java.util.zip.Inflater inf);
116 void releaseInflater0(java.util.zip.Inflater inf) {
117 releaseInflater(inf);
118 }
119
120 private static class ZipFileInputStream extends java.io.InputStream {
121 private ZipFile zf;
122 private ZipEntry ze;
123 private long pos;
124 private long count;
125
126 public ZipFileInputStream(ZipFile zf, ZipEntry ze)
127 throws java.io.IOException {
128 this.zf = zf;
129 this.ze = ze;
130 this.readLOC();
131 }
132
133 public int read(byte b[], int off, int len)
134 throws java.io.IOException {
135 long count = this.count;
136 if (TRACE)
137 System.out.println(
138 this +": reading off=" + off + " len=" + len);
139 if (count == 0) {
140 return -1;
141 }
142 if (len > count) {
143 len = (int) Math.min(count, Integer.MAX_VALUE);
144 }
145 long pos = this.pos;
146 ZipFile zf = this.zf;
147 len = zf.read(pos, b, off, len);
148 if (len == -1) {
149 throw new java.util.zip.ZipException("premature EOF");
150 }
151 this.pos = pos + len;
152 this.count = count - len;
153 return len;
154 }
155
156 public int read() throws java.io.IOException {
157 long count = this.count;
158 if (count == 0) {
159 return -1;
160 }
161 ZipFile zf = this.zf;
162 long pos = this.pos;
163 if (TRACE)
164 System.out.println(this +": reading pos=" + pos);
165 int n = zf.read(pos);
166 if (n == -1) {
167 throw new java.util.zip.ZipException("premature EOF");
168 }
169 this.pos = pos + 1;
170 this.count = count - 1;
171 if (TRACE)
172 System.out.println(this +": new pos=" + (pos + 1));
173 if (TRACE)
174 System.out.println(this +": new count=" + (count - 1));
175 return n;
176 }
177
178 public long skip(long n) {
179 long count = this.count;
180 if (n > count) {
181 n = count;
182 }
183 if (TRACE)
184 System.out.println(this +": skipping " + n);
185 long pos = this.pos;
186 this.pos = pos + n;
187 this.count = count - n;
188 if (TRACE)
189 System.out.println(this +": new pos=" + (pos + n));
190 if (TRACE)
191 System.out.println(this +": new count=" + (count - n));
192 return n;
193 }
194
195 public int available() {
196 long count = this.count;
197 return (int) Math.min(count, Integer.MAX_VALUE);
198 }
199
200 private void cleanup() {
201
202 }
203
204 public void close() {
205 cleanup();
206 }
207
208 private void readLOC() throws java.io.IOException {
209
210 byte locbuf[] = new byte[LOCHDR];
211 ZipFile zf = this.zf;
212 ZipEntry ze = this.ze;
213 long offset = ze.getOffset();
214 if (TRACE)
215 System.out.println(this +": reading LOC, offset=" + offset);
216 zf.read(offset, locbuf, 0, LOCHDR);
217 if (ZipFile.get32(locbuf, 0) != LOCSIG) {
218 throw new java.util.zip.ZipException(
219 "invalid LOC header signature");
220 }
221
222 long count = ze.getCompressedSize();
223 this.count = count;
224 if (TRACE)
225 System.out.println(this +": count=" + count);
226 long pos =
227 ze.getOffset()
228 + LOCHDR
229 + ZipFile.get16(locbuf, LOCNAM)
230 + ZipFile.get16(locbuf, LOCEXT);
231 this.pos = pos;
232 if (TRACE)
233 System.out.println(this +": pos=" + pos);
234 long cenpos = zf.cenpos;
235 if (TRACE)
236 System.out.println(this +": cenpos=" + cenpos);
237 if (pos + count > cenpos) {
238 throw new java.util.zip.ZipException(
239 "invalid LOC header format");
240 }
241 }
242 }
243 private
244 int read(long pos, byte b[], int off, int len) throws java.io.IOException {
245 if (TRACE)
246 System.out.println(
247 this
248 + ": reading file pos="
249 + pos
250 + " off="
251 + off
252 + " len="
253 + len);
254 RandomAccessFile raf = this.raf;
255 if (raf == null)
256 throw new java.io.IOException();
257 if (pos != this.pos) {
258 raf.seek(pos);
259 }
260 int n = raf.read(b, off, len);
261 if (TRACE)
262 System.out.println(this +": number read=" + n);
263 if (TRACE)
264 System.out.println(this +": current pos=" + (pos + n));
265 if (n > 0) {
266 this.pos = pos + n;
267 }
268 return n;
269 }
270 private
271 int read(long pos) throws java.io.IOException {
272 if (TRACE)
273 System.out.println(this +": read pos=" + pos);
274 RandomAccessFile raf = this.raf;
275 if (raf == null)
276 throw new java.io.IOException();
277 if (pos != this.pos) {
278 if (TRACE)
279 System.out.println(this +": seeking to " + pos);
280 raf.seek(pos);
281 }
282 int n = raf.read();
283 if (TRACE)
284 System.out.println(this +": byte read=" + n);
285 if (n > 0) {
286 this.pos = pos + 1;
287 }
288 return n;
289 }
290
291 private void readCEN() throws java.io.IOException {
292 if (TRACE)
293 System.out.println(this +": reading CEN...");
294
295 long endpos = this.findEND();
296 if (TRACE)
297 System.out.println(this +": endpos=" + endpos);
298
299 byte[] endbuf = new byte[ENDHDR];
300 RandomAccessFile raf = this.raf;
301 raf.readFully(endbuf);
302 if (get32(endbuf, 0) != ENDSIG) {
303 throw new java.util.zip.ZipException(
304 "invalid END header signature");
305 }
306
307 long cenpos = get32(endbuf, ENDOFF);
308 if (TRACE)
309 System.out.println(this +": cenpos=" + cenpos);
310 this.cenpos = cenpos;
311 int cenlen = (int) get32(endbuf, ENDSIZ);
312 if (TRACE)
313 System.out.println(this +": cenlen=" + cenlen);
314 if (cenpos + cenlen != endpos) {
315 throw new java.util.zip.ZipException("invalid END header format");
316 }
317
318 int nent = get16(endbuf, ENDTOT);
319 if (TRACE)
320 System.out.println(this +": nent=" + nent);
321 if (nent * CENHDR > cenlen) {
322 throw new java.util.zip.ZipException("invalid END header format");
323 }
324
325 if (get16(endbuf, ENDSUB) != nent) {
326 throw new java.util.zip.ZipException(
327 "cannot have more than one drive");
328 }
329
330 raf.seek(cenpos);
331 byte cenbuf[] = new byte[cenlen];
332 raf.readFully(cenbuf);
333
334 Hashtable entries = new Hashtable(nent);
335 this.entries = entries;
336 for (int off = 0; off < cenlen;) {
337
338 if (get32(cenbuf, off) != CENSIG) {
339 throw new java.util.zip.ZipException(
340 "invalid CEN header signature");
341 }
342 ZipEntry e = new ZipEntry();
343 int entrysize = e.load(cenbuf, off, cenpos, cenlen);
344 off += entrysize;
345 if (TRACE)
346 System.out.println(
347 this +": entrysize=" + entrysize + " offset=" + off);
348
349 String name = e.getName();
350 entries.put(name, e);
351 }
352 if (false) {
353
354 if (entries.size() != nent) {
355 throw new java.util.zip.ZipException(
356 "invalid CEN header format");
357 }
358 }
359 }
360
361 private static final int INBUFSIZ = 64;
362
363 private long findEND() throws java.io.IOException {
364 if (raf == null)
365 throw new java.io.IOException();
366
367 long len = raf.length();
368 if (TRACE)
369 System.out.println(this +": findEND len=" + len);
370 raf.seek(len);
371
372
373 long markpos = Math.max(0, len - 0xffff);
374
375
376
377
378
379 byte buf[] = new byte[INBUFSIZ + 4];
380 long pos = 0L;
381 for (pos = len; pos > markpos;) {
382 int n = Math.min((int) (pos - markpos), INBUFSIZ);
383 pos -= n;
384 raf.seek(pos);
385 raf.readFully(buf, 0, n);
386 while (--n > 0) {
387 if (get32(buf, n) == ENDSIG) {
388
389
390 long endpos = pos + n;
391 if (len - endpos < ENDHDR) {
392 continue;
393 }
394 raf.seek(endpos);
395 byte endbuf[] = new byte[ENDHDR];
396 raf.readFully(endbuf);
397 int comlen = get16(endbuf, ENDCOM);
398 if (TRACE)
399 System.out.println(this +": findEND comlen=" + comlen);
400 if (endpos + ENDHDR + comlen != len) {
401 continue;
402 }
403
404
405 raf.seek(endpos);
406 this.pos = endpos;
407 if (TRACE)
408 System.out.println(
409 this +": findEND pos=endpos=" + endpos);
410 return endpos;
411 }
412 }
413 }
414 throw new java.util.zip.ZipException(
415 "not a ZIP file (END header not found)");
416 }
417
418
419
420
421
422 static final int get16(byte b[], int off) {
423 return (b[off] & 0xff) | ((b[off + 1] & 0xff) << 8);
424 }
425
426
427
428
429
430 static final long get32(byte b[], int off) {
431 return get16(b, off) | ((long) get16(b, off + 2) << 16);
432 }
433
434
435 private static void freeEntry(long a, long b) {
436 Assert.UNREACHABLE();
437 }
438 }